package com.tlgen.orm.support;

import com.tlgen.orm.param.QueryParams;
import com.tlgen.orm.support.lambda.TypeFunction;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.tlgen.orm.enums.Query.*;
import static com.tlgen.orm.utils.reflect.ReflectionUtils.getLambdaFieldName;

/**
 * 高性能线程安全的查询操作构建器
 *
 * @param <T> 实体类型
 */
public class QueryOperator<T> {

    // ================= 基本比较操作 =================

    public QueryOperator<T> eq(String column, Object value) {
        return addParam(EQ.getValue(), column, value);
    }

    public QueryOperator<T> eq(TypeFunction<T, ?> fn, Object value) {
        return addParam(EQ.getValue(), getLambdaFieldName(fn), value);
    }

    public QueryOperator<T> ne(String column, Object value) {
        return addParam(NE.getValue(), column, value);
    }

    public QueryOperator<T> ne(TypeFunction<T, ?> fn, Object value) {
        return addParam(NE.getValue(), getLambdaFieldName(fn), value);
    }

    public QueryOperator<T> gt(String column, Object value) {
        return addParam(GT.getValue(), column, value);
    }

    public QueryOperator<T> gt(TypeFunction<T, ?> fn, Object value) {
        return addParam(GT.getValue(), getLambdaFieldName(fn), value);
    }

    public QueryOperator<T> ge(String column, Object value) {
        return addParam(GE.getValue(), column, value);
    }

    public QueryOperator<T> ge(TypeFunction<T, ?> fn, Object value) {
        return addParam(GE.getValue(), getLambdaFieldName(fn), value);
    }

    public QueryOperator<T> lt(String column, Object value) {
        return addParam(LT.getValue(), column, value);
    }

    public QueryOperator<T> lt(TypeFunction<T, ?> fn, Object value) {
        return addParam(LT.getValue(), getLambdaFieldName(fn), value);
    }

    public QueryOperator<T> le(String column, Object value) {
        return addParam(LE.getValue(), column, value);
    }

    public QueryOperator<T> le(TypeFunction<T, ?> fn, Object value) {
        return addParam(LE.getValue(), getLambdaFieldName(fn), value);
    }

    // ================= 逻辑操作 =================

    public QueryOperator<T> or(String column, Object value) {
        return addParam(OR.getValue(), column, value);
    }

    public QueryOperator<T> or(TypeFunction<T, ?> fn, Object value) {
        return addParam(OR.getValue(), getLambdaFieldName(fn), value);
    }

    // ================= 模糊查询操作 =================

    public QueryOperator<T> like(String column, Object value) {
        return addParam(LIKE.getValue(), column, value);
    }

    public QueryOperator<T> like(TypeFunction<T, ?> fn, Object value) {
        return addParam(LIKE.getValue(), getLambdaFieldName(fn), value);
    }

    public QueryOperator<T> notLike(String column, Object value) {
        return addParam(NOT_LIKE.getValue(), column, value);
    }

    public QueryOperator<T> notLike(TypeFunction<T, ?> fn, Object value) {
        return addParam(NOT_LIKE.getValue(), getLambdaFieldName(fn), value);
    }

    public QueryOperator<T> likeLeft(String column, Object value) {
        return addParam(LIKE_LEFT.getValue(), column, value);
    }

    public QueryOperator<T> likeLeft(TypeFunction<T, ?> fn, Object value) {
        return addParam(LIKE_LEFT.getValue(), getLambdaFieldName(fn), value);
    }

    public QueryOperator<T> likeRight(String column, Object value) {
        return addParam(LIKE_RIGHT.getValue(), column, value);
    }

    public QueryOperator<T> likeRight(TypeFunction<T, ?> fn, Object value) {
        return addParam(LIKE_RIGHT.getValue(), getLambdaFieldName(fn), value);
    }

    // ================= 范围查询操作 =================

    public QueryOperator<T> between(String column, Object start, Object end) {
        return addParam(BETWEEN.getValue(), column, asBetweenValue(start, end));
    }

    public QueryOperator<T> between(TypeFunction<T, ?> fn, Object start, Object end) {
        return addParam(BETWEEN.getValue(), getLambdaFieldName(fn), asBetweenValue(start, end));
    }

    public QueryOperator<T> notBetween(String column, Object start, Object end) {
        return addParam(NOT_BETWEEN.getValue(), column, asBetweenValue(start, end));
    }

    public QueryOperator<T> notBetween(TypeFunction<T, ?> fn, Object start, Object end) {
        return addParam(NOT_BETWEEN.getValue(), getLambdaFieldName(fn), asBetweenValue(start, end));
    }

    // ================= 空值检查操作 =================

    public QueryOperator<T> isNull(String column) {
        return addParam(IS_NULL.getValue(), column, null);
    }

    public QueryOperator<T> isNull(TypeFunction<T, ?> fn) {
        return addParam(IS_NULL.getValue(), getLambdaFieldName(fn), null);
    }

    public QueryOperator<T> isNotNull(String column) {
        return addParam(IS_NOT_NULL.getValue(), column, null);
    }

    public QueryOperator<T> isNotNull(TypeFunction<T, ?> fn) {
        return addParam(IS_NOT_NULL.getValue(), getLambdaFieldName(fn), null);
    }

    // ================= 集合操作 =================

    public QueryOperator<T> in(String column, Collection<?> values) {
        validateCollection(values, "IN");
        return addParam(IN.getValue(), column, values);
    }

    public QueryOperator<T> in(TypeFunction<T, ?> fn, Collection<?> values) {
        validateCollection(values, "IN");
        return addParam(IN.getValue(), getLambdaFieldName(fn), values);
    }

    public QueryOperator<T> notIn(String column, Collection<?> values) {
        validateCollection(values, "NOT IN");
        return addParam(NOT_IN.getValue(), column, values);
    }

    public QueryOperator<T> notIn(TypeFunction<T, ?> fn, Collection<?> values) {
        validateCollection(values, "NOT IN");
        return addParam(NOT_IN.getValue(), getLambdaFieldName(fn), values);
    }

    // ================= 分组和排序操作 =================

    public QueryOperator<T> groupBy(String... columns) {
        return addParam(GROUP_BY.getValue(), String.join(", ", columns), null);
    }

    @SafeVarargs
    public final QueryOperator<T> groupBy(TypeFunction<T, ?>... fns) {
        return addParam(GROUP_BY.getValue(), getFieldNames(fns), null);
    }

    public QueryOperator<T> orderByAsc(String... columns) {
        return addParam(ORDER_BY_ASC.getValue(), String.join(", ", columns), null);
    }

    @SafeVarargs
    public final QueryOperator<T> orderByAsc(TypeFunction<T, ?>... fns) {
        return addParam(ORDER_BY_ASC.getValue(), getFieldNames(fns), null);
    }

    public QueryOperator<T> orderByDesc(String... columns) {
        return addParam(ORDER_BYD_ESC.getValue(), String.join(", ", columns), null);
    }

    @SafeVarargs
    public final QueryOperator<T> orderByDesc(TypeFunction<T, ?>... fns) {
        return addParam(ORDER_BYD_ESC.getValue(), getFieldNames(fns), null);
    }

    private static final String BETWEEN_DELIMITER = "&&";
    private final List<QueryParams> paramsList = new ArrayList<>();

    // 私有构造函数，使用工厂方法创建实例
    public QueryOperator() {}

    /**
     * 创建新的空查询操作对象
     */
    public static <T> QueryOperator<T> empty() {
        return new QueryOperator<>();
    }

    /**
     * 获取只读参数列表视图
     */
    public List<QueryParams> getParamsList() {
        return Collections.unmodifiableList(paramsList);
    }

    // ================= 核心私有方法 =================

    /**
     * 添加参数并返回新对象
     */
    private QueryOperator<T> addParam(String operator, String column, Object value) {
        QueryOperator<T> copy = this.copy();
        copy.paramsList.add(createParam(operator, column, value));
        return copy;
    }

    /**
     * 创建查询参数对象
     */
    private QueryParams createParam(String operator, String column, Object value) {
        QueryParams param = new QueryParams();
        param.setOperator(operator);
        param.setColumn(column);
        param.setValue(value);
        return param;
    }

    /**
     * 复制当前对象状态
     */
    private QueryOperator<T> copy() {
        QueryOperator<T> clone = new QueryOperator<>();
        // 浅拷贝参数列表(QueryParams是值对象)
        clone.paramsList.addAll(this.paramsList);
        return clone;
    }

    /**
     * 处理 BETWEEN 参数的特殊格式
     */
    private String asBetweenValue(Object start, Object end) {
        if (start == null || end == null) {
            throw new IllegalArgumentException("BETWEEN操作参数不能为空");
        }
        return start + BETWEEN_DELIMITER + end;
    }

    /**
     * 从Lambda获取字段名称
     */
    @SafeVarargs
    private final String getFieldNames(TypeFunction<T, ?>... fns) {
        if (fns == null || fns.length == 0) {
            throw new IllegalArgumentException("至少提供一个函数参数");
        }

        return Stream.of(fns)
                .map(fn -> {
                    try {
                        return getLambdaFieldName(fn);
                    } catch (Exception e) {
                        throw new IllegalArgumentException("无效的Lambda表达式", e);
                    }
                })
                .collect(Collectors.joining(", "));
    }

    /**
     * 验证集合参数
     */
    private void validateCollection(Collection<?> values, String operation) {
        if (CollectionUtils.isEmpty(values)) {
            throw new IllegalArgumentException(operation + "操作需要非空集合");
        }
    }

    /**
     * 添加 AND 连接符
     */
    public QueryOperator<T> and() {
        // 无需特殊处理，链式调用即为 AND 关系
        return this;
    }

}